package com.gitee.cliveyuan.tools.web;

import com.gitee.cliveyuan.tools.Assert;
import com.gitee.cliveyuan.tools.FileTools;
import com.gitee.cliveyuan.tools.MathTools;
import com.gitee.cliveyuan.tools.StringTools;
import com.gitee.cliveyuan.tools.bean.FileUploadRequest;
import com.gitee.cliveyuan.tools.bean.FileUploadResponse;
import com.gitee.cliveyuan.tools.exception.FileUploadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * 文件上传工具类
 *
 * @author clive
 * Created on 2018/07/27
 * @since 2.0.7
 */
public class FileUploadTools {

    private static final Logger logger = LoggerFactory.getLogger(FileUploadTools.class);

    private FileUploadTools() {
    }

    /**
     * 文件上传
     *
     * @throws FileUploadException
     */
    public static FileUploadResponse upload(FileUploadRequest fileUploadRequest) throws FileUploadException {
        Assert.notNull(fileUploadRequest, "fileUploadRequest is required");
        MultipartFile multipartFile = fileUploadRequest.getMultipartFile();
        HttpServletRequest request = fileUploadRequest.getRequest();
        String relativeSavePath = fileUploadRequest.getRelativeSavePath();
        String absoluteSavePath = fileUploadRequest.getAbsoluteSavePath();
        String fileName = fileUploadRequest.getFileName();
        String allowedExtensions = fileUploadRequest.getAllowedExtensions();

        Assert.notNull(multipartFile, "multipartFile is required");
        Assert.notNull(request, "request is required");
        Assert.isTrue(StringTools.isNotBlank(relativeSavePath)
                || StringTools.isNotBlank(absoluteSavePath), "relativeSavePath and absoluteSavePath can't be both blank");

        try {
            if (multipartFile.getSize() > 0) {
                String extension = FileTools.getExtension(multipartFile.getOriginalFilename());
                Assert.notEmpty(extension, "can't get the extension");
                if (StringTools.isNotEmpty(allowedExtensions)) {
                    List<String> allowedExtensionList = Arrays.asList(allowedExtensions.toLowerCase().split(","));
                    if (!allowedExtensionList.contains(extension.toLowerCase())) {
                        throw FileUploadException.notSupport("not support this file:"
                                + extension + ", only support " + allowedExtensions);
                    }
                }
                // 上传文件
                String path = absoluteSavePath;
                if (StringTools.isNotBlank(relativeSavePath)) {
                    path = request.getSession().getServletContext().getRealPath(relativeSavePath);
                }
                if (StringTools.isBlank(path)) throw FileUploadException.uploadPathNotExist();

                if (StringTools.isBlank(fileName)) {
                    fileName = Long.toString(System.currentTimeMillis()) + MathTools.randomInt(1000000, 9999999);
                }
                String fullFileName = fileName + "." + extension;
                File targetDirectory = new File(path);
                if (!targetDirectory.exists()) {
                    boolean mkdirs = targetDirectory.mkdirs();
                    if (!mkdirs) throw FileUploadException.failToMkdirs(targetDirectory.getAbsolutePath());
                }
                File targetFile = new File(path, fullFileName);
                multipartFile.transferTo(targetFile);

                return FileUploadResponse.builder()
                        .fileName(fullFileName)
                        .fileRealPath(path + "/" + fullFileName)
                        .webRelativePath(request.getContextPath() + "/" + relativeSavePath + "/" + fullFileName)
                        .length(targetFile.length())
                        .extension(extension)
                        .build();
            } else {
                logger.warn("file is null or file size equals zero");
                throw FileUploadException.fileEmpty();
            }
        } catch (FileUploadException e) {
            throw e;
        } catch (Exception e) {
            logger.error("file upload exception", e);
            throw FileUploadException.unKnowError();
        }

    }
}
